﻿using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text.RegularExpressions;

namespace Carbon.Web.Forms.jQueryForms
{
    public class TextBoxEditor : TextBox, IEditor, IScriptControl
    {
		#region Classes (1)
		private class TextBoxScriptDescriptor : ScriptDescriptor
        {
			#region Fields (1)
			private TextBoxEditor m_Editor = default(TextBoxEditor);
			#endregion

			#region Properties (1)
			public TextBoxEditor Editor
            {
                get
                {
                    return m_Editor;
                }
            }
			#endregion

			#region Constructors (1)
			public TextBoxScriptDescriptor(TextBoxEditor editor)
                : base()
            {
                if (editor == null) throw new ArgumentNullException("editor");

                this.m_Editor = editor;
            }
			#endregion

			#region Methods (1)

			protected override string GetScript()
            {
                return Editor.GetClientScript();
            }

			#endregion
        }
		#endregion

		#region Fields (3)
		private SimpleEditor m_Editor = default(SimpleEditor);

		protected String m_Value = null;
		#endregion

		#region Properties (3)
		public SimpleEditor Editor
        {
            get
            {
                return m_Editor;
            }
        }
		public bool IsNull
        {
            get
            {
                return string.IsNullOrEmpty(m_Value);
            }
        }
		public virtual object Value
        {
            get
            {
                return m_Value;
            }
            set
            {
                if (this.Editor.ErrorDuringUpdateModel && !Editor.StoreInvalidValueInViewModel)
                {
                    value = this.Editor.Text;
                }
                m_Value = (String)value;
                this.Text = (String)value;

                if (Editor.StoreInvalidValueInViewModel)
                {
                    if (Validate(m_Value))
                    {
                        this.Editor.ErrorDuringUpdateModel = false;
                        this.Editor.ErrorTextDuringUpdateModel = null;
                    }
                }
            }
        }
		#endregion

		#region Constructors (1)
		public TextBoxEditor(SimpleEditor editor)
            : base()
        {
            if (editor == null) throw new ArgumentNullException("editor");

            this.m_Editor = editor;
        }
		#endregion

		#region ASP Processing

		protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
        }

        private bool Validate(String value)
        {
            this.Editor.ErrorTextDuringUpdateModel = null;
            this.Editor.ShowErrorText = false;
            this.Editor.ErrorDuringUpdateModel = false;

            if (!this.Editor.CanBeNull && string.IsNullOrEmpty(value))
            {
                this.Editor.ErrorDuringUpdateModel = true;
                this.Editor.ShowErrorText = false;
                this.Editor.ErrorTextDuringUpdateModel = Errors.InvalidValue;
                return false;
            }

            if (!string.IsNullOrEmpty(Editor.ValidationRegex) && !string.IsNullOrEmpty(value))
            {
                if (!Regex.IsMatch(value, Editor.ValidationRegex))
                {
                    this.Editor.ErrorDuringUpdateModel = true;
                    this.Editor.ErrorTextDuringUpdateModel = this.Editor.ValidationRegexErrorMessage;
                    return false;
                }
            }

            if (Editor.MaxLength.HasValue)
            {
                if (value != null && value.Length > Editor.MaxLength)
                {
                    this.Editor.ErrorDuringUpdateModel = true;
                    this.Editor.ErrorTextDuringUpdateModel = Errors.MaxLengthExceeeded(Editor.MaxLength.Value);
                    return false;
                }
            }

            return true;
        }

        protected virtual void ReturnValue()
        {
            if (!Validate(Editor.Text))
            {
                if (!Editor.StoreInvalidValueInViewModel)
                    return;
            }

            this.m_Value = Editor.Text;
        }

		protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
        {
            bool result = base.LoadPostData(postDataKey, postCollection);

            Editor.Text = this.Text;

            String beforeValue = m_Value;
            ReturnValue();

            if (m_Value != beforeValue)
            {
                if (Editor.AutoPostback)
                {
                    m_Value = beforeValue;
                    return true;
                }
            }

            return false;
        }

		protected override void RaisePostDataChangedEvent()
        {
            base.RaisePostDataChangedEvent();

            if (Editor.AutoPostback)
            {
                ReturnValue();
                this.RaiseBubbleEvent(this, new UpdateModelEventArgs());
            }
        }

        protected virtual void RegisterScripts()
        {
            this.Editor.ScriptManager.RegisterScriptControl(this);
            this.Editor.ScriptManager.RegisterScriptDescriptors(this);
        }

		protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            RegisterScripts();
            
            this.AutoPostBack = Editor.AutoPostback;

            this.Width = Editor.Width;
            this.Height = Editor.Height;
            this.TextMode = Editor.TextMode;
            this.EnableViewState = false;

            if (!this.Editor.AddDefaultContainerBoxes)
            {
                this.CssClass = Editor.CssClass;
            }
        }

		#endregion

		#region Methods (3)

		protected virtual String GetClientScript()
        {
            String regex = Editor.ValidationRegex;

            if (regex == null)
                regex = "null";
            else
                regex = "\"" + Editor.ValidationRegex.Replace("\\", "\\\\") + "\"";

            String validationRegexErrorMessage = "null";

            if (!string.IsNullOrEmpty(Editor.ValidationRegexErrorMessage))
                validationRegexErrorMessage = "\"" + InternalUtility.EncodeJavascriptString(Editor.ValidationRegexErrorMessage) + "\"";

            if (!string.IsNullOrEmpty(Editor.ValidationRegex))
            {
                if (string.IsNullOrEmpty(Editor.ValidationRegexErrorMessage)) throw new ArgumentOutOfRangeException("Editor.ValidationRegexErrorMessage");
            }

            String maxLegth = "null";

            if (Editor.MaxLength.HasValue)
                maxLegth = ConvertInvariant.ToString(Editor.MaxLength);

            return string.Format("Carbon.Web.Forms.jQueryForms.TextEditor(\"{0}\", {1}, {2}, {3}, {4});", this.ClientID, ConvertInvariant.ToString(this.Editor.CanBeNull).ToLower(), regex, validationRegexErrorMessage, maxLegth);
        }

		public virtual IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            return new ScriptDescriptor[] { new TextBoxScriptDescriptor(this) };
        }

		public virtual IEnumerable<ScriptReference> GetScriptReferences()
        {
            return new ScriptReference[] {};
        }


        public override void RenderControl(HtmlTextWriter writer)
        {
            base.RenderControl(writer);
        }
		#endregion
    }
}